
global nodo_crear
global lista_crear
global lista_borrar
global lista_imprimir
global lista_imprimir_f
global crear_jugador
global menor_jugador
global normalizar_jugador
global pais_jugador
global borrar_jugador
global imprimir_jugador
global crear_seleccion
global menor_seleccion
global primer_jugador
global borrar_seleccion
global imprimir_seleccion
global insertar_ordenado
global mapear
global ordenar_lista_jugadores
global altura_promedio

extern malloc
extern free
extern fprintf
extern fopen
extern fclose
extern filtrar_jugadores
extern insertar_ultimo

;AUXILIAR
global string_copiar
global string_iguales
global string_comparar

; SE RECOMIENDA COMPLETAR LOS DEFINES CON LOS VALORES CORRECTOS
%define NULL 0
%define TRUE 1
%define FALSE 0

%define NODO_SIZE      24 
%define LISTA_SIZE     16 
%define JUGADOR_SIZE   21 
%define SELECCION_SIZE 24 

%define OFFSET_DATOS 0
%define OFFSET_SIG   8 
%define OFFSET_ANT   16 

%define OFFSET_PRIMERO 0
%define OFFSET_ULTIMO  8 

%define OFFSET_NOMBRE_J 0
%define OFFSET_PAIS_J   8 
%define OFFSET_NUMERO_J 16 
%define OFFSET_ALTURA_J 17 

%define OFFSET_PAIS_S      0
%define OFFSET_ALTURA_S    8 
%define OFFSET_JUGADORES_S 16 

section .rodata

section .data

format_j: db "%s %s %hhd %d ",10,0
format_s: db "%s %.2lf ",10,0
formato_vac: db "<vacia>",10,0
append: db "a",0

section .text

;AUXILIARES SUGERIDOS

; FUNCIONES AUXILIARES.

;char *string_copiar(char *s)
string_copiar:
        ;rdi(*s)
        push rbp
        mov rbp, rsp
        push rbx
        sub rsp, 8

        mov rbx, rdi

        ;longitud del string
        xor rax, rax

.cicloAvanzar:
        cmp byte [rdi], NULL
        je .finCiclo
        inc rdi
        inc rax
        jmp .cicloAvanzar

.finCiclo:
        inc rax
        mov rdi, rax
        call malloc
        mov rcx, rax

        ;copio el string

.cicloCpy:
        mov r8b, byte [rbx]
        mov byte [rcx], r8b
        cmp byte [rbx], NULL
        je .finCpy
        inc rcx
        inc rbx
        jmp .cicloCpy

.finCpy:
        add rsp, 8
        pop rbx
        pop rbp
        ret

string_iguales:
        ;rdi(*s1) rsi(*s2)
        push rbp
        mov rbp, rsp

        xor rax, rax

.cicloAvanzar:
        cmp byte [rdi], NULL
        je .finCiclo
        mov r8b, byte [rdi]
        cmp r8b, byte [rsi]
        jne .fin
        inc rdi
        inc rsi
        jmp .cicloAvanzar

.finCiclo:
        cmp byte [rsi], NULL
        je .finE
        jmp .fin

.finE:
        mov al, 1

.fin:
        pop rbp
        ret

string_comparar:
        ;rdi(*s1) rsi(*s2)
        push rbp
        mov rbp, rsp
        push rbx
        push r12

        mov rbx, rdi
        mov r12, rsi

        call string_iguales
        cmp al, 1
        je .Iguales

.cicloAvanzar:
        cmp byte [rbx], NULL
        je .EsMenor
        mov r8b, byte [rbx]
        cmp r8b, byte [r12]
        jne .finNE
        inc rbx
        inc r12
        jmp .cicloAvanzar

.finNE:
        cmp r8b, [r12]
	jl .EsMenor
        mov eax, 1
        jmp .fin

.EsMenor:
        mov eax, -1
        jmp .fin

.Iguales:
        xor rax, rax

.fin:
        pop r12
        pop rbx
        pop rbp
        ret

;void insertar_antes_de(lista* l, nodo* nuevo, nodo* n)
insertar_antes_de:
        ;rdi(*l) rsi(*nuevo) rdx(*n)
        push rbp
        mov rbp, rsp

        mov r8, qword [rdi+OFFSET_PRIMERO]
        cmp r8, rdx
        je .vaPrimero

.cicloAvanzar:
        cmp qword [r8+OFFSET_SIG], rdx
        je .insertar
        mov r8, qword [r8+OFFSET_SIG]
        jmp .cicloAvanzar

.insertar:
        mov qword [rsi+OFFSET_SIG], rdx
        mov qword [rsi+OFFSET_ANT], r8
        mov qword [rdx+OFFSET_ANT], rsi
      	mov qword [r8+OFFSET_SIG], rsi
	jmp .fin

.vaPrimero:
        mov qword [rdi+OFFSET_PRIMERO], rsi
        mov qword [rsi+OFFSET_SIG], rdx
        mov qword [rdx+OFFSET_ANT], rsi

.fin:
        pop rbp
        ret

; FUNCIONES OBLIGATORIAS. PUEDEN CREAR LAS FUNCIONES AUXILIARES QUE CREAN CONVENIENTES

nodo_crear:
	;rdi(*dato)
	push rbp
	mov rbp, rsp
	push r12
	sub rsp, 8

	mov r12, rdi
	mov rdi, NODO_SIZE
	call malloc 
	mov qword [rax+OFFSET_DATOS], r12
	mov qword [rax+OFFSET_SIG], NULL
	mov qword [rax+OFFSET_ANT], NULL	
	
	add rsp, 8
	pop r12
	pop rbp
	ret


lista_crear:
	;rdi(void)
	push rbp
	mov rbp, rsp
	mov rdi, LISTA_SIZE
	call malloc 
	mov qword [rax+OFFSET_PRIMERO], NULL
	mov qword [rax+OFFSET_ULTIMO], NULL
	pop rbp
	ret

lista_borrar:
	;rdi(lista* l) rsi(f)
	push rbp
	mov rbp, rsp
	push rbx
	push r12
	push r13
	sub rsp, 8

	mov rbx, rdi
	mov r12, [rdi+OFFSET_PRIMERO]
	mov r13, rsi 

.cicloAvanzar1: 		;primero libero los datos de la lista
	cmp r12, NULL 
	je .fin1
	mov rdi, qword [r12+OFFSET_DATOS]
	call r13
	mov r12, qword [r12+OFFSET_SIG]		
	jmp .cicloAvanzar1

.fin1:
	mov rdi, rbx
	mov rbx, qword [rbx+OFFSET_PRIMERO]
	call free 

.cicloAvanzar2:			;segundo borro los nodos que conforman la lista
	cmp rbx, NULL
	je .fin2
	mov rdi,rbx
	mov rbx, qword [rbx+OFFSET_SIG]		
	call free
	jmp .cicloAvanzar2

.fin2:	
	add rsp, 8
	pop r13
	pop r12
	pop rbx
	pop rbp	
	ret

lista_imprimir:
	;rdi(*l) rsi(*nombre_archivo) rdx(f)
	push rbp
	mov rbp, rsp
	push rbx
	push r12

	mov rbx, rdi
	mov r12, rdx

	mov rdi, rsi
	mov rsi, append
	call fopen

	mov rdi, rbx
	mov rsi, rax
	mov rdx, r12
	mov r12, rax
	call lista_imprimir_f

	mov rdi, r12
	call fclose
	
	pop r12
	pop rbx
	pop rbp
	ret

lista_imprimir_f:
	; rdi(*l) rsi(*file) rdx(f)
	push rbp
	mov rbp, rsp
	push rbx
	push r12
	push r13
	sub rsp, 8

	mov rbx, qword [rdi+OFFSET_PRIMERO]
	mov r12, rsi
	mov r13, rdx
	
	cmp rbx, NULL
        je .vacia
	.cicloAvanzar:	
	cmp rbx, NULL
	je .fin
	mov rdi, qword [rbx+OFFSET_DATOS]
	mov rsi, r12
	call r13
	mov rbx, qword [rbx+OFFSET_SIG]
	jmp .cicloAvanzar

.vacia:
	mov rax,1
	mov rdi, rsi
	mov rsi, formato_vac	
	call fprintf

.fin:
	add rsp, 8
	pop r13
	pop r12
	pop rbx
	pop rbp
	ret

crear_jugador:
	;rdi(*nombre) rsi(*pais) dl(numero) ecx(altura)
	push rbp
	mov rbp, rsp
	push rbx 
	push r12
	push r13
	push r14
		
	mov rbx, rdi
	mov r12, rsi
	mov r13b, dl
	mov r14d, ecx
	
	call string_copiar
	mov rbx, rax
	
	mov rdi, r12
	call string_copiar
	mov r12, rax

	mov rdi, JUGADOR_SIZE
	call malloc
	mov qword [rax+OFFSET_NOMBRE_J], rbx
	mov qword [rax+OFFSET_PAIS_J], r12
	mov byte [rax+OFFSET_NUMERO_J], r13b
	mov dword [rax+OFFSET_ALTURA_J], r14d

	pop r14
	pop r13
	pop r12
	pop rbx
	pop rbp
	ret

menor_jugador:
	;rdi(*j1) rsi(*j2)
	push rbp
	mov rbp, rsp
	push rbx 
	push r12
	
	mov rbx, rdi
	mov r12, rsi

	mov rdi, [rdi+OFFSET_NOMBRE_J]
	mov rsi, [rsi+OFFSET_NOMBRE_J]

	call string_comparar
	cmp eax, 0
	je .altura
	jl .menor
	jg .mayor 

.altura:
	mov edx, dword [rbx+OFFSET_ALTURA_J]
	cmp edx, dword [r12+OFFSET_ALTURA_J]
	jl .menor
	je .menor
.mayor:
        xor rax, rax
        jmp .fin

.menor:	
	mov al,1 
	jmp .fin

.fin:
	pop r12
	pop rbx
	pop rbp
	ret

normalizar_jugador:
	; rdi(*j)
	push rbp
	mov rbp, rsp
	%define  pies [rbp-8]
	sub rsp, 8
	push rbx

	mov rbx, rdi

	mov rdi, qword [rbx+OFFSET_NOMBRE_J] 	;nombre
	mov rsi, qword [rbx+OFFSET_PAIS_J]   	;pais
	mov dl, byte [rbx+OFFSET_NUMERO_J]	;numero
	mov ecx, dword [rbx+OFFSET_ALTURA_J]	;altura

	call crear_jugador
	mov r8, rax
	
	mov r8, [rax+OFFSET_NOMBRE_J]
	cmp byte [r8], NULL
        je .fin
	inc r8

.cicloAvanzar:
	cmp byte [r8], NULL
	je .fin
	cmp byte [r8], 91
	jl .nada
	sub byte [r8], 32
.nada:
	inc r8
	jmp .cicloAvanzar
	
.fin:
	mov r9, rax

	cvtsi2ss xmm0, dword [r9+OFFSET_ALTURA_J]
	mov dword pies, 0x41f3d70a	
	divss xmm0,  pies
	cvttss2si eax, xmm0
	mov dword [r9+OFFSET_ALTURA_J], eax	

	mov rax, r9
	pop rbx
	add rsp, 8
	pop rbp
	ret

pais_jugador:
	; rdi(*j1) rsi(*j2)
	push rbp
	mov rbp, rsp
	mov rdi, [rdi+OFFSET_PAIS_J]
	mov rsi, [rsi+OFFSET_PAIS_J]
	call string_iguales
	pop rbp
	ret

borrar_jugador:
	;rdi(*j)
	push rbp
	mov rbp, rsp
	push rbx
	sub rsp, 8	

	mov rbx, rdi
	mov rdi, [rbx+OFFSET_NOMBRE_J]
	call free
	mov rdi, [rbx+OFFSET_PAIS_J]
	call free	
	mov rdi, rbx
	call free

	add rsp, 8
	pop rbx 	
	pop rbp
	ret	

imprimir_jugador:
	;rdi(*j) rsi(*file)
	push rbp
	mov rbp, rsp
	mov rax,1 ;frpintf
	
	mov r10, rdi

	mov rdi, rsi
	mov rsi, format_j
	mov rdx, qword [r10+OFFSET_NOMBRE_J]
	mov rcx, qword [r10+OFFSET_PAIS_J]	
	mov r8b, byte [r10+OFFSET_NUMERO_J]
	mov r9d, dword [r10+OFFSET_ALTURA_J]	

	call fprintf
	
	pop rbp
	ret

crear_seleccion:
	;rdi(*pais) xmm0(altura_promedio) rsi(*jugadores)
	push rbp
	mov rbp, rsp
	%define alt [rbp-8]
	sub rsp, 8
	push rbx
	push r12
	sub rsp, 8

	mov r12, rsi	

	movsd alt,xmm0 

	call string_copiar
	mov rbx, rax

	mov rdi, SELECCION_SIZE
	call malloc
	mov qword [rax+OFFSET_PAIS_S], rbx
	mov r8, alt
	mov qword [rax+OFFSET_ALTURA_S], r8
	mov qword [rax+OFFSET_JUGADORES_S], r12

	add rsp, 8
	pop r12
	pop rbx
	add rsp, 8
	pop rbp
	ret

menor_seleccion:
	; rdi(*s1) rsi(*s2)
	push rbp
	mov rbp, rsp
	mov rdi, qword [rdi+OFFSET_PAIS_S]
	mov rsi, qword [rsi+OFFSET_PAIS_S]
	call string_comparar
	cmp eax, -1
	je .menor
	
	xor rax, rax
	jmp .fin

.menor:
	mov eax, 1

.fin:
	pop rbp
	ret

primer_jugador:
	; rdi(*s)
	push rbp
	mov rbp, rsp
	mov rax, qword [rdi+OFFSET_JUGADORES_S]
	mov rax, qword [rax+OFFSET_PRIMERO]
	mov rax, qword [rax+OFFSET_DATOS]
	mov rdi, qword [rax+OFFSET_NOMBRE_J]  ;nombre
        mov rsi, qword [rax+OFFSET_PAIS_J]    ;pais
        mov dl, byte [rax+OFFSET_NUMERO_J]   ;numero
        mov ecx, dword [rax+OFFSET_ALTURA_J]  ;altura
	call crear_jugador	

	pop rbp
	ret

borrar_seleccion:
	; rdi(*s)
	push rbp
	mov rbp, rsp
	push rbx
	sub rsp, 8
	
	mov rbx, rdi
	mov rdi, qword [rbx+OFFSET_PAIS_S]
	call free					;borra el string crado con malloc 
	mov rdi, qword [rbx+OFFSET_JUGADORES_S]	
	mov rsi, borrar_jugador
	call lista_borrar				;borra la lista de jugadore de la seleccion
	mov rdi, rbx
	call free					;borra la seleccion

	add rsp, 8
	pop rbx
	pop rbp
	ret

imprimir_seleccion:
	; rdi(*s) rsi(*file)
	push rbp
	mov rbp, rsp
	push rbx
	push r12
	
	mov rbx, rdi
	mov r12, rsi
	mov rax,1
	
	mov rdi, rsi
	mov rsi, format_s
	mov rdx, qword [rbx+OFFSET_PAIS_S] 
	movq xmm0, qword [rbx+OFFSET_ALTURA_S]
	call fprintf
	
	mov rdi, qword [rbx+OFFSET_JUGADORES_S]
	mov rsi, r12	
	mov rdx, imprimir_jugador
	call lista_imprimir_f

	pop r12
	pop rbx
	pop rbp
	ret

insertar_ordenado:
	;rdi(*l) rsi(*datos) rdx(f)
	push rbp
	mov rbp, rsp
	push rbx 
	push r12
	push r13
	push r14
	push r15
	sub rsp, 8
	
	mov rbx, rdi
	mov r12, rdx
	mov r13, rsi	
	mov r14, rbx

	mov rdi, rsi
	call nodo_crear	
	mov r15, rax

	cmp qword [rbx+OFFSET_PRIMERO], NULL
	je .insertPrim	
	mov r8, qword [rbx+OFFSET_PRIMERO] 
	mov rdi, r13
	mov rsi, qword [r8+OFFSET_DATOS]
	call r12
	cmp al, 1
	je .insertPrim2

	mov rbx, qword [rbx+OFFSET_PRIMERO]

.cicloAvanzar:
	cmp qword [rbx+OFFSET_SIG], NULL
	je .insertUlt
	mov rbx, qword [rbx+OFFSET_SIG]
	mov rdi, r13 
	mov rsi, qword [rbx+OFFSET_DATOS]
	call r12
	cmp al, 1
	je .insertar
	jmp .cicloAvanzar

.insertar:
	mov rdi, r14
	mov rsi, r15
	mov rdx, rbx 	
	call insertar_antes_de
	jmp .fin

.insertPrim:
	mov qword [rbx+OFFSET_PRIMERO], r15
	mov qword [rbx+OFFSET_ULTIMO], r15
	jmp .fin
	 		
.insertPrim2:
	mov r8, qword [rbx+OFFSET_PRIMERO]
	mov qword [rbx+OFFSET_PRIMERO], r15
	mov qword [r8+OFFSET_ANT], r15	
	mov qword [r15+OFFSET_SIG], r8 
	jmp .fin

.insertUlt:
	mov qword [rbx+OFFSET_SIG], r15
	mov qword [r15+OFFSET_ANT], rbx
	mov qword [r14+OFFSET_ULTIMO],r15

.fin:
	add rsp, 8
	pop r15
	pop r14
	pop r13
	pop r12
	pop rbx 
	pop rbp
	ret

altura_promedio:
	; rdi(*l)
	push rbp
	mov rbp, rsp
	%define sum [rbp-8]
	sub rsp, 16	

	pxor xmm1, xmm1
	pxor xmm0, xmm0
	xor r9, r9
	movsd sum, xmm0

	mov r8, qword [rdi+OFFSET_PRIMERO] 
	cmp r8, NULL
	je .vacia

.cicloAvanzar:
	cmp r8, NULL
	je .fin
	mov rcx, qword [r8+OFFSET_DATOS]
	mov ecx, dword [rcx+OFFSET_ALTURA_J]	
	cvtsi2sd xmm1, ecx
	addsd xmm0, xmm1
	mov r8, qword [r8+OFFSET_SIG]
	inc r9
	jmp .cicloAvanzar

.fin:
	cvtsi2sd xmm1, r9
	divsd xmm0, xmm1 	

.vacia:
	add rsp, 16
	pop rbp
	ret

ordenar_lista_jugadores:
	; rdi(*l)
	push rbp
	mov rbp, rsp
	push rbx
	push r12

	mov rbx, qword [rdi+OFFSET_PRIMERO]
	call lista_crear
	mov r12, rax

.cicloAvanzar:
	cmp rbx, NULL
	je .fin
 	mov r8, qword [rbx+OFFSET_DATOS]
	mov rdi, qword [r8+OFFSET_NOMBRE_J]  ;nombre
        mov rsi, qword [r8+OFFSET_PAIS_J]    ;pais
        mov dl, byte [r8+OFFSET_NUMERO_J]   ;numero
        mov ecx, dword [r8+OFFSET_ALTURA_J]  ;altura
        call crear_jugador
	mov rdi, r12
	mov rsi, rax 		
	mov rdx, menor_jugador
	call insertar_ordenado
	mov rbx, qword [rbx+OFFSET_SIG]
	jmp .cicloAvanzar

.fin:
	mov rax, r12
	pop r12
	pop rbx
	pop rbp
	ret

mapear:
	; rdi(*l) rsi(f)
	push rbp
	mov rbp, rsp
	push rbx
	push r12
	push r13
	sub rsp, 8

	mov rbx, qword [rdi+OFFSET_PRIMERO]
	mov r12, rsi

	call lista_crear
	mov r13, rax
	
.cicloAvanzar:
	cmp rbx, NULL
	je .fin
	mov rdi, qword [rbx+OFFSET_DATOS]
	call r12
	mov rdi, rax
	call nodo_crear
	mov rdi, r13
	mov rsi, rax
	call insertar_ultimo
	mov rbx, qword [rbx+OFFSET_SIG]
	jmp .cicloAvanzar

.fin:
	mov rax, r13
	add rsp, 8
	pop r13
	pop r12
	pop rbx
	pop rbp
	ret

